#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define CRW_IMPL
#include "parStr.h"
#include "cw.h"
#include "error.h"


struct scw {
  FILE * f;
  bool isStdOut;
  bool arr;
};

cw
cw_create(char * f){

/*
  DESC: Constructor. Toma el nombre de archivo.
  Si el archivo existe lo borra.
  Si es vacio toma la salida estandard.
  Devuelve NULL si no hay memoria.
  PRE: { c = NULL /\ f -> F }
  c = cw_create(f);  
  POS: {  Hay memoria ==>  c --> cw(F)   
  ! Hay memoria ==>  c = NULL  }   
*/
  cw c;

  assert(f != NULL);

  c = NULL;

  c = (cw) malloc(sizeof(struct scw));

  if (c != NULL){

    c->arr = FALSE;

    if (f[0] == '\0'){
      warnx("cw_create use stdout"); 
      c->isStdOut = TRUE;
      c->f = stdout;
    } else {
      c->isStdOut = FALSE;
      c->f = fopen (f, "w");
    }    
    if (c->f == NULL){
      warn(ERRFMT,"cw_create",__LINE__);
      free(c);
      c = NULL;

    }
  }

  return c;
}

cw
cw_destroy(cw c){
/*
  DESC: Destructor del tipo. c cambia.
  PRE: { c --> C }
  c = cw_destroy(c);
  POS: { Se destruye C /\ c == NULL }
*/
  assert(c != NULL);
  assert(c->f != NULL);

  if (! c->isStdOut)
    fclose(c->f);

  c->f = NULL;

  free(c);
  c = NULL;
  
  return c;
}

cw
cw_arr(cw c){
/*
DESC: Arranca la cinta.
PRE: { c --> C }
   c = cw_arr(c);
POS: {  Hay memoria /\ ! Error de Archivo ==> Pi(*c)=[] /\ Pd(*c)=[]
      ! Hay memoria  \/  Error de Archivo ==> Se destruye C /\ c = NULL}
*/
  assert(c != NULL);
  assert(c->f != NULL);
  assert(c->arr == FALSE);

  c->arr = TRUE;

  return  c;

}

cw
cw_insert(cw c, elem e){
/*
DESC: Inserta un elemento al final.
PRE: { c-->C /\ Pi(C) = Pi /\ Pd(C) = [] }
   c = cw_insert(c);
POS: {  Hay memoria /\ ! Error de Archivo ==> Pi(*c)=Pi:e /\ Pd(*c)=[]
      ! Hay memoria  \/  Error de Archivo ==> Se destruye C /\ c = NULL}
*/
  assert(c != NULL);
  assert(c->f != NULL);
  assert(c->arr == TRUE);
  assert(e != NULL);

  if (!parStr_toStream(c->f, e))
    c = cw_destroy(c);

  return c;

}
